package com.tju.resource.server.impl;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tju.resource.common.ServiceException;
import com.tju.resource.mapper.SysUserRoleMapper;
import com.tju.resource.tool.result.Result;
import com.tju.resource.tool.result.ResultEnum;
import com.tju.resource.tool.result.ResultUtil;
import com.tju.resource.mapper.SysRoleMapper;
import com.tju.resource.mapper.SysRolePermissionMapper;
import com.tju.resource.model.*;
import com.tju.resource.tool.tool.ClientParameters;
import com.tju.resource.server.SysRoleService;
import com.tju.resource.tool.tool.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

import static com.tju.resource.tool.tool.ListUtils.*;

/**
 * 角色业务实现
 *
 * @Author CLS
 * @Date 2021/12/31 14:22
 */
@Slf4j
@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    SysRoleMapper mapper;

    @Autowired
    SysUserRoleMapper urMapper;

    @Autowired
    SysRolePermissionMapper rpMapper;

    @Override
    public SysRole getCharacter(Long cId) {
        return mapper.selectById(cId);
    }

    @Override
    public Result<Object> getCharacterAll(ClientParameters parameter) {
        try {
            Page<SysRole> page = new Page<>(parameter.getPage(), parameter.getLimit());
            IPage<SysRole> iPage = mapper.getCharacterAll(page, parameter);
            List<SysRole> records = iPage.getRecords();

            records.forEach(this::setSrRoles);

            return ResultUtil.success(ResultEnum.SUCCESS, records, iPage.getTotal());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    @Transactional
    public Long addCharacter(Map<String, String> params) {
        SysRole sysRole = new SysRole();
        JSONArray roles = new JSONArray();
        StringBuilder halfRoles = new StringBuilder();
        JSONArray half = JSONUtil.parseArray(params.get("half"));

        sysRole.setName(params.get("name"));
        sysRole.setRemark(params.get("remark"));

        mapper.addCharacter(sysRole);

        if (null != params.get("half") && null != params.get("full")) {
            half.forEach(e -> halfRoles.append(e).append(","));
            roles.addAll(JSONUtil.parseArray(params.get("full")));
            roles.addAll(half);

            if (halfRoles.length() != 0) {
                if (halfRoles.reverse().charAt(0) == ',') {
                    halfRoles.deleteCharAt(0).reverse();
                }
            }

            remDup(roles);
            batchIns(roles, sysRole.getId(), halfRoles.toString(), half);
        }

        return sysRole.getId();
    }

    @Override
    @Transactional
    public int updCharacter(Map<String, String> params) {
        SysRole sysRole = mapper.selectById(Integer.parseInt(params.get("id")));
        int updRes;
        JSONArray roles = new JSONArray();
        StringBuilder halfRoles = new StringBuilder();
        JSONArray half = JSONUtil.parseArray(params.get("half"));

        sysRole.setName(params.get("name"));
        sysRole.setRemark(params.get("remark"));
        sysRole.setUpdateDate(new Date());

        updRes = mapper.updateById(sysRole);

        if (null != params.get("half") && null != params.get("full")) {
            roles.addAll(JSONUtil.parseArray(params.get("full")));
            half.forEach(e -> halfRoles.append(e).append(","));
            roles.addAll(half);

            if (halfRoles.length() != 0) {
                if (halfRoles.reverse().charAt(0) == ',') {
                    halfRoles.deleteCharAt(0).reverse();
                }
            }

            remDup(roles);
            batchDelSRP(sysRole.getId());

            batchIns(roles, sysRole.getId(), halfRoles.toString(), half);
        }

        return updRes;
    }

    @Transactional
    @Override
    public int delCharacter(Map<String, String> params) {
        Long roleId = Long.parseLong(params.get("id"));
        int delRes;

        if (getUsersRoles(roleId)==0) {
            delRes = mapper.deleteById(roleId);
            batchDelSRP(roleId);
        } else {
            throw new ServiceException("该角色已被使用！");
        }
        return delRes;
    }

    @Transactional
    public void batchIns(JSONArray roles, Long roleId, String halfRoles, JSONArray halfArr) {
        List<SysRolePermission> cRoles = new ArrayList<>();
        boolean f = false;

        remDup(roles);
        for (Object role : roles) {
            Long rId = Long.parseLong(role + "");
            SysRolePermission srp = new SysRolePermission();

            srp.setRoleId(roleId);
            srp.setPermissionId(rId);
            srp.setIsHalf("false");

            if (!f) {
                srp.setHalfRoles(halfRoles);
                f = true;
            }

            halfArr.forEach(ele -> {
                if (StringUtils.equals(ele + "", rId + "")) {
                    srp.setIsHalf("true");
                }
            });

            cRoles.add(srp);
        }

        cRoles.forEach(rpMapper::insert);
    }

    @Transactional
    public void batchDelSRP(Long roleId) {
        QueryWrapper<SysRolePermission> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        rpMapper.delete(wrapper);
    }

    @Override
    @SuppressWarnings("unchecked")
    public boolean hasRoleName(String roleName) {
        ClientParameters parameter = new ClientParameters();
        List<SysRole> data;

        parameter.setPage(1);
        parameter.setLimit(10);
        parameter.setOne(roleName);

        data = (List<SysRole>) getCharacterAll(parameter).getData();

        return 0 != data.size();
    }

    public JSONArray getSrRoles(Long roleId) {
        QueryWrapper<SysRolePermission> query = new QueryWrapper<>();
        List<SysRolePermission> queryResult;
        JSONArray ja = new JSONArray();

        query.eq("role_id", roleId);
        queryResult = rpMapper.selectList(query);
        queryResult.forEach(ele -> {
            if (!StringUtils.equals("true", ele.getIsHalf())) {
                ja.add(ele.getPermissionId());
            }
        });

        return ja;
    }

    public JSONArray getSrHalf(Long roleId) {
        QueryWrapper<SysRolePermission> query = new QueryWrapper<>();
        AtomicReference<JSONArray> result = new AtomicReference<>();

        query.eq("role_id", roleId);

        rpMapper.selectList(query).forEach(ele -> {
            if (null == result.get()) {
                String[] split = ele.getHalfRoles().split(",");
                List<String> sl = new ArrayList<>(Arrays.asList(split));

                result.set(JSONUtil.parseArray(sl));
            }
        });

        return result.get();
    }

    public void setSrRoles(SysRole sr) {
        sr.setRoles(getSrRoles(sr.getId()));
        sr.setHalfRoles(getSrHalf(sr.getId()));
    }

    public int getUsersRoles(Long roleId) {
        QueryWrapper<SysUserRole> query = new QueryWrapper<>();
        List<SysUserRole> result;

        query.eq("role_id", roleId);
        result = urMapper.selectList(query);

        return null == result ? 0 : result.size();
    }
}
